#include "common/RhoConf.h"
#include "common/RhodesApp.h"
#include "sync/RhoconnectClientManager.h"
#include "sync/ILoginListener.h"
#include "Push.h"

#ifdef WINCE
#include "../../platform/wm/src/PushClient.h"
#endif

#include "logging/RhoLog.h"

#include "anspushclient.h"

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "ANSPUSH"
#ifdef WINCE
#define ANS_APP "\\Program Files\\rhoconnect-push-service\\rhoconnect-push.exe"
#endif

extern "C" {

void anspush_install_service();
void anspush_ans_register(const char* username, const char* password, const char* session);
void anspush_ans_unregister(const char* session);
void anspush_check_ans_registration(const char* session);

// declare Ruby registration method generated by SWIG in ans_push_wrap.c
extern "C" void rho_wmsys_run_app(const char* szPath, const char* szParams );

// this method executed once on start of program
RHO_GLOBAL void Init_RhoConnectPush_extension(void) {
    // execute initialization of Ruby registration (generated by SWIG)
    RAWLOG_INFO("Init_RhoConnectPush_extension()");

// TODO: Move platform specific code to class derived from AnsPushClient
#ifdef WINCE
    rho_wmsys_run_app(ANS_APP, "");
    if(GetLastError() == -1)
    {
	LOG(ERROR) + "rhoconnect-push.exe doesn't exist";
	PushClient::Disable();
    }
#endif
    // create RC push client
    RAWTRACEC("Init_RhoConnectPush_extension", "creating push client >>>>>>>>>>>>>>");
    
    rho::ans::AnsPushClient* pClient = new rho::ans::AnsPushClient();

    RAWTRACEC("Init_RhoConnectPush_extension", "adding push client >>>>>>>>>>>>>>>>");

    rho::push::CPushManager::getInstance()->addClient(pClient);

    RAWTRACEC("Init_RhoConnectPush_extension", "initialization has finished >>>>>>>>>>>>>>>>");
}

} //extern "C"


namespace rho { namespace ans {

//----------------------------------------------------------------------------------------------------------------------
class AnsPushClient::SyncLoginListener : public sync::ILoginListener
{
public:
    virtual ~SyncLoginListener() {}
    virtual void onLogin(const String& user, const String& pass, const String& session) const;
    virtual void onLogout(const String& session) const;
};

//----------------------------------------------------------------------------------------------------------------------
void AnsPushClient::SyncLoginListener::onLogin(const String& user, const String& pass, const String& session) const
{
    RAWTRACEC("SyncLoginListener", "onLogin >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
    anspush_ans_register(user.c_str(), pass.c_str(), session.c_str());
}
//----------------------------------------------------------------------------------------------------------------------
void AnsPushClient::SyncLoginListener::onLogout(const String& session) const
{
    RAWTRACEC("SyncLoginListener", "onLogout <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
    sync::RhoconnectClientManager::clientRegisterSetDevicePin("");
    anspush_ans_unregister(session.c_str());
}
//----------------------------------------------------------------------------------------------------------------------
const String AnsPushClient::s_Type = "rhoconnect";

AnsPushClient::AnsPushClient()
{
    CMethodResult result;
    setProperty("id", s_Type, result);
    setProperty("type", IPush::PUSH_TYPE_RHOCONNECT, result);
    setProperty("pushServer", RHOCONF().getString("Push.rhoconnect.pushServer"), result);
    setProperty("pushAppName", RHOCONF().getString("Push.rhoconnect.pushAppName"), result);

    anspush_install_service();

    LOG(TRACE) + "adding login listener >>>>>>>>>>>>>>>>";
    sync::RhoconnectClientManager::clientRegisterAddLoginListener(new SyncLoginListener());

    LOG(TRACE) + "creating client register >>>>>>>>>>>>>>>>";
    rho::sync::RhoconnectClientManager::clientRegisterCreate();

    LOG(TRACE) + "AnsPushClient has created >>>>>>>>>>>>>>>>";
}

//----------------------------------------------------------------------------------------------------------------------
void AnsPushClient::getDeviceId(CMethodResult& result)
{
    String deviceId = m_hashProps["deviceId"];

    if(deviceId.length() != 0)
    {
        LOG(TRACE) + "Rhoconnect-push deviceId: " + deviceId;
        result.set(deviceId);
    }
    else
    {
        LOG(TRACE) + "Still waiting for Rhoconnect-push deviceId";
        m_deviceIdResult = result;
    }
}

//----------------------------------------------------------------------------------------------------------------------
void AnsPushClient::setDeviceId(const String& deviceId)
{
    LOG(TRACE) + "Set Rhoconnect-push deviceId: " + deviceId;

    CMethodResult result;
    setProperty("deviceId", deviceId, result);

    sync::RhoconnectClientManager::clientRegisterCreate(deviceId.c_str());

    getDeviceId(m_deviceIdResult);
    m_deviceIdResult = CMethodResult();
}

//----------------------------------------------------------------------------------------------------------------------
void AnsPushClient::startNotifications(CMethodResult& result)
{
    LOG(TRACE) + "Start Rhoconnect-push notifications";
    m_oResult = result;
}

//----------------------------------------------------------------------------------------------------------------------
void AnsPushClient::stopNotifications(CMethodResult& result)
{
    LOG(TRACE) + "Stop Rhoconnect-push notifications";
    m_oResult = CMethodResult();
}

//----------------------------------------------------------------------------------------------------------------------
bool AnsPushClient::callBack(const String& json)
{
    LOG(TRACE) + "Rhoconnect-push notification: " + json;

    m_oResult.setJSON(json);

    return true;
}

}}

